package org.laobai.generation;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.*;

import org.laobai.generation.utils.JDBCUtil;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

public class CodeGeneratorWithForm extends JFrame {
	private static final long serialVersionUID = 1L;

	private final static AutoGenerator mpg = new AutoGenerator();
	private JFrame parent;
	private JLabel authorLabel = new JLabel("作者名：");
	private JTextField authorField = new JTextField(System.getenv().get("USERNAME"));
	private JLabel linkedLabel = new JLabel("数据库IP&端口号 ：");
	private JTextField linkedField = new JTextField("localhost:3306");
	private JLabel dbNameLabel = new JLabel("数据库名：");
	private JTextField dbNameField = new JTextField("");
	private JButton selectDBBtn = new JButton("库名");
	private JLabel tableNameLabel = new JLabel("要生成的表(选填)：");
	private JTextField tableNameField = new JTextField("");
	private JLabel userLabel = new JLabel("用户名：");
	private JTextField userField = new JTextField("root");
	private JLabel pwdLabel = new JLabel("密码：");
	private JTextField pwdField = new JTextField("root");
	private JLabel packageLabel = new JLabel("包名：");
	private JTextField packageField = new JTextField("");
	private JLabel tablePixLabel = new JLabel("表名前缀：");
	private JTextField tablePixField = new JTextField("t_");
	private JLabel pathLabel = new JLabel("生成路径：");
	private JTextField pathField = new JTextField("");
	private JButton selectBtn = new JButton("路径");

	private JButton okBtn = new JButton("OK");
	private JLabel alertLabel = new JLabel("");

	private JLabel mkByLabel = new JLabel("Copyright © bp 21.04.09");

	private JFileChooser fileChooser = new JFileChooser();

	// 包名路径
	private String packagePath = "";
	private String projectPath = System.getProperty("user.dir");
	// 是否生成boot的main方法
	private boolean isMain = true;

	public CodeGeneratorWithForm(boolean isMain) {
		this.isMain = isMain;
	}

	public void init() {
		parent = this;
		this.setLayout(null);
		this.setSize(400, 635);
		this.setLocationRelativeTo(null);

		this.setTitle("一键生成-v3.0");

		this.setVisible(true);
		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		List<JLabel> labels = new ArrayList<>();
		List<JTextField> fields = new ArrayList<>();
		labels.add(authorLabel);
		fields.add(authorField);
		labels.add(userLabel);
		fields.add(userField);
		labels.add(pwdLabel);
		fields.add(pwdField);
		labels.add(linkedLabel);
		fields.add(linkedField);
		labels.add(dbNameLabel);
		fields.add(dbNameField);
		labels.add(tableNameLabel);
		fields.add(tableNameField);
		labels.add(tablePixLabel);
		fields.add(tablePixField);
		labels.add(packageLabel);
		fields.add(packageField);
		labels.add(pathLabel);
		fields.add(pathField);


		for (int i = 0; i < labels.size(); i++) {
			int y = 20+50*i;
			labels.get(i).setBounds(20,y,130,40);
			this.add(labels.get(i));

			fields.get(i).setBounds(150,y,140,40);
			this.add(fields.get(i));
		}

		selectDBBtn.setBounds(300, 230, 80, 25);
		this.add(selectDBBtn);

		selectBtn.setBounds(300, 430, 80, 25);//410
		this.add(selectBtn);
//320
		okBtn.setBounds(150, 495, 100, 40);//465
		this.add(okBtn);

		alertLabel.setBounds(125, 540, 160, 20);
		this.add(alertLabel);

		mkByLabel.setBounds(135,565,160,20);
		this.add(mkByLabel);
	}

	public void myEvent() {
		selectDBBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 获取表名
				String[] dbNames = new String[0];
				try {
					dbNames = JDBCUtil.findTableByDatabase(linkedField.getText(),
							userField.getText(), pwdField.getText());
				} catch (Exception ex) {
					JOptionPane.showMessageDialog(null, "请检查数据库连接信息", "报错了",JOptionPane.ERROR_MESSAGE);
					return;
				}
				// 选择数据库
				String dbName = (String) JOptionPane.showInputDialog(null,"请选择数据库:\n",
						"请选择数据库", JOptionPane.PLAIN_MESSAGE,
						null, dbNames, "");

//				JList list = new JList(dbNames);
//				String s = JOptionPane.showInputDialog(null, list, "Select Test Case (For Multiple Selections Press 'Ctrl') ", JOptionPane.PLAIN_MESSAGE);
//				System.out.println(s);

				// 设置数据库信息
				dbNameField.setText(dbName);
			}
		});
		selectBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				fileChooser.setCurrentDirectory(new File(pathField.getText()));
				fileChooser.setDialogTitle("请选择要上传的文件...");
				fileChooser.setApproveButtonText("确定");
				fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				int result = fileChooser.showOpenDialog(parent);
				if (JFileChooser.APPROVE_OPTION == result) {
					pathField.setText(fileChooser.getSelectedFile().getPath());
				}
			}
		});
		okBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				alertLabel.setText("");
				alertLabel.setFont(new Font("谐体", Font.BOLD, 15));
				if (isEmpty(authorField, dbNameField, userField, pwdField, packageField, tablePixField)) {
					alertLabel.setForeground(Color.RED);
					alertLabel.setText("!!请填写以上所有项!!");
					return;
				}
				// 获取包路径
				packagePath = packageField.getText().replace(".", "\\");
				disposeDB();
				try {
					mpg.execute();
					// disposeFiles();
					alertLabel.setForeground(Color.GREEN);
					alertLabel.setText("!!********成功********!!");
				} catch (Exception e1) {
					e1.printStackTrace();
					System.out.println("----" + e1.getMessage());
					alertLabel.setText("!!********失败********!!");
				}

			}
		});
	}

	public void disposeArgs(String author,String user,String pwd,String packageName,String dbName,String path) {

		// 作者名 数据库名 用户名 密码 包名
		if(!StringUtils.isEmpty(author)){
			authorField.setText(author);
		}
		if(!StringUtils.isEmpty(user)){
			userField.setText(user);
		}
		if(!StringUtils.isEmpty(pwd)){
			pwdField.setText(pwd);
		}
		if(!StringUtils.isEmpty(packageName)){
			packageField.setText(packageName);
		}
		if(!StringUtils.isEmpty(dbName)){
			dbNameField.setText(dbName);
		}
		if(!StringUtils.isEmpty(path)){
			pathField.setText(path);
		}
	}

	private void disposeDB() {
		// 全局配置
		GlobalConfig globalConfig = new GlobalConfig();
		String path = pathField.getText();
		if(!StringUtils.isEmpty(path)){
			projectPath = path;
		}
		globalConfig.setOutputDir(projectPath + "/src/main/java")
				// TODO 修改作者
				.setAuthor(authorField.getText()).setOpen(false).setBaseColumnList(true).setFileOverride(true)
				.setBaseResultMap(true).setServiceName("%sService") // 设置生成的service接口的名字的首字母是否为I
				.setDateType(DateType.ONLY_DATE);
		mpg.setGlobalConfig(globalConfig);

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		// TODO 设置数据库名
		dsc.setUrl("jdbc:mysql://"+linkedField.getText()+"/" + dbNameField.getText()
				+ "?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");
		dsc.setDriverName("com.mysql.cj.jdbc.Driver");
		dsc.setUsername(userField.getText());
		dsc.setPassword(pwdField.getText());
		mpg.setDataSource(dsc);

		// 包配置
		PackageConfig pc = new PackageConfig();
		// TODO 修改包名
		pc.setParent(packageField.getText());
		pc.setEntity("entity");
		pc.setController("controller");
		pc.setMapper("mapper");
		pc.setService("service");
		pc.setServiceImpl("service.impl");
		mpg.setPackageInfo(pc);

		List<FileOutConfig> fileOutConfigList = new ArrayList<FileOutConfig>();
		// XML
		fileOutConfigList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/resources/mapper/" + "/" + tableInfo.getEntityName() + "Mapper"
						+ StringPool.DOT_XML;
			}
		});
		// Controller
		// fileOutConfigList.add(new FileOutConfig("/ftl/controller.java.ftl") {
		// @Override
		// public String outputFile(TableInfo tableInfo) {
		// return projectPath + "/src/main/java/" + packagePath + "/controller/"
		// + tableInfo.getEntityName() + "Controller"
		// + StringPool.DOT_JAVA;
		// }
		// });
		//
		// // Mapper
		// fileOutConfigList.add(new FileOutConfig("/ftl/mapper.java.ftl") {
		// @Override
		// public String outputFile(TableInfo tableInfo) {
		// System.out.println(projectPath + "/src/main/java/" + packagePath +
		// "/mapper/" + tableInfo.getEntityName() + "Mapper"
		// + StringPool.DOT_JAVA);
		// return projectPath + "/src/main/java/" + packagePath + "/mapper/" +
		// tableInfo.getEntityName() + "Mapper"
		// + StringPool.DOT_JAVA;
		// }
		// });

		// config
		fileOutConfigList.add(new FileOutConfig("/templates/PageConfig.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/config/PageConfig" + StringPool.DOT_JAVA;
			}
		});
		fileOutConfigList.add(new FileOutConfig("/templates/WebConfig.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/config/WebConfig" + StringPool.DOT_JAVA;
			}
		});

		// util
		fileOutConfigList.add(new FileOutConfig("/templates/DateUtils.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/util/DateUtils" + StringPool.DOT_JAVA;
			}
		});
		fileOutConfigList.add(new FileOutConfig("/templates/StringUtils.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/util/StringUtils" + StringPool.DOT_JAVA;
			}
		});
		fileOutConfigList.add(new FileOutConfig("/templates/FileUtils.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/util/FileUtils" + StringPool.DOT_JAVA;
			}
		});


		// struct
		fileOutConfigList.add(new FileOutConfig("/templates/PageResult.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/struct/PageResult" + StringPool.DOT_JAVA;
			}
		});
		fileOutConfigList.add(new FileOutConfig("/templates/Result.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/struct/Result" + StringPool.DOT_JAVA;
			}
		});
		// vo
		fileOutConfigList.add(new FileOutConfig("/templates/SearchVO.java.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/java/" + packagePath + "/vo/SearchVO" + StringPool.DOT_JAVA;
			}
		});

		// properties
		fileOutConfigList.add(new FileOutConfig("/templates/application.properties.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/resources/" +"/application.properties";
			}
		});

		// vue
		fileOutConfigList.add(new FileOutConfig("/templates/vue.vue.ftl") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return projectPath + "/src/main/resources/page/" + tableInfo.getEntityName() + ".vue";
			}
		});

		// main
		if(isMain){
			fileOutConfigList.add(new FileOutConfig("/templates/WebStarter.java.ftl") {
				@Override
				public String outputFile(TableInfo tableInfo) {
					return projectPath + "/src/main/java/" + packagePath + "/WebStarter" + StringPool.DOT_JAVA;
				}
			});
		}


		InjectionConfig injectionConfig = new InjectionConfig() {
			@Override
			public void initMap() {
				Map<String, Object> map = new HashMap<>();
				map.put("basePackage", packageField.getText());
				this.setMap(map);
			}
		};

		injectionConfig.setFileOutConfigList(fileOutConfigList);
		mpg.setCfg(injectionConfig);

		// 配置模板
		TemplateConfig templateConfig = new TemplateConfig();
		templateConfig.setXml(null);
		mpg.setTemplate(templateConfig);

		// 策略配置
		StrategyConfig strategy = new StrategyConfig();
		strategy.setNaming(NamingStrategy.underline_to_camel);
		strategy.setColumnNaming(NamingStrategy.underline_to_camel);
		strategy.setEntityTableFieldAnnotationEnable(true);
		// 设置表
		String tableNames = tableNameField.getText();
		if (StringUtils.isEmpty(tableNames)) {
			// 选择所有表
			strategy.setExclude("");
		} else {
			// 选择指定表
			strategy.setInclude(tableNames.split(","));
		}

		strategy.setControllerMappingHyphenStyle(true);
		// TODO 更改数据库表前缀
		strategy.setTablePrefix(tablePixField.getText());
		// 设置restful
		strategy.setRestControllerStyle(true);

		mpg.setStrategy(strategy);
		mpg.setTemplateEngine(new FreemarkerTemplateEngine());
	}

	private boolean isEmpty(JTextField... fields) {
		for (JTextField field : fields) {
			String str = field.getText();
			if (str == null || str.equals("")) {
				return true;
			}
		}
		return false;
	}


}